package com.jml.第二期.config;


import com.jml.第二期.entity.PermissionEntity;
import com.jml.第二期.filter.JWTLoginFilter;
import com.jml.第二期.filter.JWTValidationFilter;
import com.jml.第二期.mapper.PermissionMapper;
import com.jml.第二期.service.MemberUserDetailsService;
import com.jml.第二期.utils.MD5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import java.util.List;


@Component
@EnableWebSecurity  //开启框架权限
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private MemberUserDetailsService memberUserDetailsService;
    @Autowired
    private PermissionMapper permissionMapper;

    /**
     * 添加授权账户
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        // 设置用户账号信息和权限
//        auth.inMemoryAuthentication().withUser("admin").password("jml")
                    //设置用户权限
//                .authorities("addMember", "delMember", "updateMember", "showMember");
//        // 如果admin账户权限的情况 所有的接口都可以访问，如果jml_add 只能访问addMember
//        auth.inMemoryAuthentication().withUser("jml_add").password("jml")
            //设置用户权限
//                .authorities("addMember");
        auth.userDetailsService(memberUserDetailsService).passwordEncoder(new PasswordEncoder() {
            /**
             * 对密码MD5
             * @param rawPassword
             * @return
             */
            @Override
            public String encode(CharSequence rawPassword) {
                return MD5Util.encode((String) rawPassword);
            }

            /**
             * rawPassword 用户输入的密码
             * encodedPassword 数据库DB的密码
             * @param rawPassword
             * @param encodedPassword
             * @return
             */
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                String rawPass = encode(rawPassword);
                boolean result = rawPass.equals(encodedPassword);
                return result;
            }
        });
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        //配置httpBasic Http协议认证   这是弹窗登录
////        http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().httpBasic();
//        //配置httpBasic Http协议认证   这是表单登录
//          http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().formLogin();
//        // 默认fromLog   項目启动的时候调用配置权限
        List<PermissionEntity> allPermission = permissionMapper.findAllPermission();
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry
                expressionInterceptUrlRegistry = http.authorizeRequests();
        allPermission.forEach((permission) -> {
            //匹配哪些url要授权，需要哪些权限
            expressionInterceptUrlRegistry.antMatchers(permission.getUrl()).
            //需要哪些权限才能访问url
                    hasAnyAuthority(permission.getPermTag());

        });
        // 整合jwt前后端分离  /auth/login 所有人都有这个url的权限
        expressionInterceptUrlRegistry.antMatchers("/auth/login").permitAll()
                //所有的请求未授权就跳转到login
                .antMatchers("/**").fullyAuthenticated().and()
                .addFilter(new JWTValidationFilter(authenticationManager()))
                .addFilter(new JWTLoginFilter(authenticationManager())).csrf().disable()
                //剔除session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);


        /*
        //这个是在做前后端一体的，如果整合jwt前后端分离就不用formLogin了，用postman测试
        /login 这个url有所有人都有权限，登录页面是login页面
        expressionInterceptUrlRegistry.antMatchers("/login").permitAll()
                //所有的请求未授权就跳转到login
        .antMatchers("/**").fullyAuthenticated().and()
        .formLogin().loginPage("/login").and().csrf().disable();
        */
    }


    /**
     * 报错：There is no PasswordEncoder mapped for the id "null"
     * 原因:升级为Security5.0以上密码支持多中加密方式需要加密，加上下面的配置就可以恢复以前模式不用加密
     *
     * @return
     */
    @Bean
    public static NoOpPasswordEncoder passwordEncoder() {
        return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
    }

}
